home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // File: usefuldi.cpp
- //
- // Desc: Contains various DInput-specific utility classes and functions
- // to help the UI carry its operations more easily.
- //
- // Copyright (C) Microsoft Corporation. All Rights Reserved.
- //-----------------------------------------------------------------------------
-
- #include "common.hpp"
-
- // don't want useful.cpp to use precompiled header
- #include "useful.cpp"
-
-
- BOOL IsObjectOnExcludeList(DWORD dwOfs)
- {
- if (dwOfs == DIK_PREVTRACK ||
- dwOfs == DIK_NEXTTRACK ||
- dwOfs == DIK_MUTE ||
- dwOfs == DIK_CALCULATOR ||
- dwOfs == DIK_PLAYPAUSE ||
- dwOfs == DIK_MEDIASTOP ||
- dwOfs == DIK_VOLUMEDOWN ||
- dwOfs == DIK_VOLUMEUP ||
- dwOfs == DIK_WEBHOME ||
- dwOfs == DIK_SLEEP ||
- dwOfs == DIK_WEBSEARCH ||
- dwOfs == DIK_WEBFAVORITES ||
- dwOfs == DIK_WEBREFRESH ||
- dwOfs == DIK_WEBSTOP ||
- dwOfs == DIK_WEBFORWARD ||
- dwOfs == DIK_WEBBACK ||
- dwOfs == DIK_MYCOMPUTER ||
- dwOfs == DIK_MAIL ||
- dwOfs == DIK_MEDIASELECT ||
- dwOfs == DIK_LWIN ||
- dwOfs == DIK_RWIN ||
- dwOfs == DIK_POWER ||
- dwOfs == DIK_WAKE)
- return TRUE;
-
- return FALSE;
- }
-
- BOOL CALLBACK IncrementValPerObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
- {
- if (pvRef != NULL)
- ++(*((int *)pvRef));
- return DIENUM_CONTINUE;
- }
-
- BOOL CALLBACK KeyboardIncrementValPerObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
- {
- if (pvRef != NULL && !IsObjectOnExcludeList(lpddoi->dwOfs))
- ++(*((int *)pvRef));
- return DIENUM_CONTINUE;
- }
-
- BOOL CALLBACK FillDIDeviceObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
- {
- if (pvRef == NULL || lpddoi == NULL)
- return DIENUM_CONTINUE;
-
- DIDEVOBJSTRUCT &os = *((DIDEVOBJSTRUCT *)pvRef);
- assert(os.pdoi != NULL);
- assert(os.n < os.nObjects);
- if (os.pdoi != NULL && os.n < os.nObjects)
- os.pdoi[os.n++] = *lpddoi;
-
- return DIENUM_CONTINUE;
- }
-
- // This is a special EnumObjects() callback for keyboard type devices. When we enumerate, dwOfs
- // member of lpddoi is meaningless. We need to take the middle 16 bits of dwType as dwOfs
- // (also same as DIK_xxx).
- BOOL CALLBACK FillDIKeyboardDeviceObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
- {
- if (pvRef == NULL || lpddoi == NULL || IsObjectOnExcludeList(lpddoi->dwOfs))
- return DIENUM_CONTINUE;
-
- DIDEVOBJSTRUCT &os = *((DIDEVOBJSTRUCT *)pvRef);
- assert(os.pdoi != NULL);
- assert(os.n < os.nObjects);
- if (os.pdoi != NULL && os.n < os.nObjects)
- {
- os.pdoi[os.n] = *lpddoi;
- os.pdoi[os.n].dwOfs = os.pdoi[os.n].dwType >> 8;
- wcscpy(os.pdoi[os.n].tszName, lpddoi->tszName);
- ++os.n;
- }
-
- return DIENUM_CONTINUE;
- }
-
- HRESULT FillDIDeviceObjectStruct(DIDEVOBJSTRUCT &os, LPDIRECTINPUTDEVICE8W pDID)
- {
- if (pDID == NULL)
- return E_FAIL;
-
- DIDEVICEINSTANCEW didi;
- didi.dwSize = sizeof(didi);
- pDID->GetDeviceInfo(&didi);
-
- HRESULT hr;
- if (LOBYTE(didi.dwDevType) == DI8DEVTYPE_KEYBOARD)
- hr = pDID->EnumObjects(KeyboardIncrementValPerObject, &os.nObjects,
- DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
- else
- hr = pDID->EnumObjects(IncrementValPerObject, &os.nObjects,
- DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
- if (FAILED(hr))
- {
- os.nObjects = 0;
- return hr;
- }
-
- if (os.nObjects == 0)
- return S_OK;
-
- if (os.pdoi != NULL)
- free(os.pdoi);
- os.pdoi = (DIDEVICEOBJECTINSTANCEW *)malloc(sizeof(DIDEVICEOBJECTINSTANCEW) * os.nObjects);
- if (os.pdoi == NULL)
- {
- os.nObjects = 0;
- return E_FAIL;
- }
-
- // Check if this device is a keyboard. If so, it needs special treatment.
- os.n = 0;
- if ((didi.dwDevType & 0xFF) == DI8DEVTYPE_KEYBOARD)
- {
- hr = pDID->EnumObjects(FillDIKeyboardDeviceObject, &os,
- DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
- } else {
- hr = pDID->EnumObjects(FillDIDeviceObject, &os,
- DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
- }
-
- if (FAILED(hr))
- {
- os.nObjects = 0;
- return hr;
- }
-
- assert(os.nObjects == os.n);
- os.nObjects = os.n;
-
- return S_OK;
- }
-
- LPTSTR AllocConfigureFlagStr(DWORD dwFlags)
- {
- static const AFS_FLAG flag[] = {
- #define f(F) { F, _T(#F) }
- f(DICD_EDIT), f(DICD_DEFAULT)
- #undef f
- };
- static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
- return AllocFlagStr(dwFlags, flag, flags);
- }
-
- LPTSTR AllocActionFlagStr(DWORD dwFlags)
- {
- static const AFS_FLAG flag[] = {
- #define f(F) { F, _T(#F) }
- f(DIA_FORCEFEEDBACK),
- f(DIA_APPMAPPED),
- f(DIA_APPNOMAP),
- f(DIA_NORANGE),
- #undef f
- }; static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
- return AllocFlagStr(dwFlags, flag, flags);
- }
-
- LPTSTR AllocActionHowFlagStr(DWORD dwFlags)
- {
- static const AFS_FLAG flag[] = {
- #define f(F) { F, _T(#F) }
- f(DIAH_UNMAPPED),
- f(DIAH_USERCONFIG),
- f(DIAH_APPREQUESTED),
- f(DIAH_HWAPP),
- f(DIAH_HWDEFAULT),
- f(DIAH_DEFAULT),
- f(DIAH_ERROR)
- #undef f
- }; static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
- return AllocFlagStr(dwFlags, flag, flags);
- }
-
- void CleanupActionFormatCopy(DIACTIONFORMATW &c)
- {
- if (c.rgoAction != NULL)
- {
- for (DWORD i = 0; i < c.dwNumActions; i++)
- if (c.rgoAction[i].lptszActionName != NULL)
- free((LPTSTR)c.rgoAction[i].lptszActionName);
- free(c.rgoAction);
- }
- c.rgoAction = NULL;
- }
-
- HRESULT CopyActionFormat(DIACTIONFORMATW &to, const DIACTIONFORMATW &from)
- {
- DWORD i;
-
- // copy all simple members
- to = from;
-
- // null copied pointers since we're going to duplicate them (makes sure cleanup works)
- to.rgoAction = NULL;
-
- // handle pointers/arrays/strings
- to.rgoAction = new DIACTIONW [to.dwNumActions];
- if (to.rgoAction == NULL)
- goto fail;
-
- // first null it all
- memset(to.rgoAction, 0, sizeof(DIACTIONW) * to.dwNumActions);
-
- // now copy...
- for (i = 0; i < to.dwNumActions; i++)
- {
- // copy simple members
- to.rgoAction[i] = from.rgoAction[i];
-
- // handle pointers/arrays/strings
- to.rgoAction[i].lptszActionName = _wcsdup(from.rgoAction[i].lptszActionName);
- if (to.rgoAction[i].lptszActionName == NULL)
- goto fail;
- }
-
- return S_OK;
- fail:
- CleanupActionFormatCopy(to);
- return E_OUTOFMEMORY;
- }
-
- LPDIACTIONFORMATW DupActionFormat(LPCDIACTIONFORMATW lpAcFor)
- {
- if (!lpAcFor)
- return NULL;
-
- LPDIACTIONFORMATW pdup = new DIACTIONFORMATW;
- if (!pdup)
- return NULL;
-
- if (FAILED(CopyActionFormat(*pdup, *lpAcFor)))
- {
- delete pdup;
- return NULL;
- }
-
- return pdup;
- }
-
- void FreeActionFormatDup(LPDIACTIONFORMATW &lpAcFor)
- {
- if (!lpAcFor)
- return;
-
- CleanupActionFormatCopy(*lpAcFor);
- delete lpAcFor;
- lpAcFor = NULL;
- }
-
- void TraceActionFormat(LPTSTR header, const DIACTIONFORMATW &acf)
- {
- #ifdef CFGUI__TRACE_ACTION_FORMATS
- tracescope(a, header);
- trace(_T("\n"));
-
- traceDWORD(acf.dwSize);
- traceDWORD(acf.dwActionSize);
- traceDWORD(acf.dwDataSize);
- traceDWORD(acf.dwNumActions);
- {tracescope(b, _T("acf.rgoAction Array\n"));
- for (DWORD i = 0; i < acf.dwNumActions; i++)
- {
- const DIACTIONW &a = acf.rgoAction[i];
- static TCHAR buf[MAX_PATH];
- _stprintf(buf, _T("Action %d\n"), i);
- {tracescope(c, buf);
- traceHEX(a.uAppData);
- traceDWORD(a.dwSemantic);
- LPTSTR str = AllocActionFlagStr(a.dwFlags);
- trace1(_T("a.dwFlags = %s\n"), str);
- free(str);
- traceWSTR(a.lptszActionName);
- traceUINT(a.uResIdString);
- traceDWORD(a.dwObjID);
- traceGUID(a.guidInstance);
- str = AllocActionHowFlagStr(a.dwHow);
- trace1(_T("a.dwHow = %s\n"), str);
- free(str);
- }
- }
- }
- traceGUID(acf.guidActionMap);
- traceDWORD(acf.dwGenre);
- traceDWORD(acf.dwBufferSize);
- traceLONG(acf.lAxisMin);
- traceLONG(acf.lAxisMax);
- traceHEX(acf.hInstString);
- traceHEX(acf.dwCRC);
- traceWSTR(acf.tszActionMap);
- #endif
- }
-
- BOOL IsZeroOrInvalidColorSet(const DICOLORSET &cs)
- {
- if (cs.dwSize < sizeof(DICOLORSET))
- return TRUE;
-
- const int colors = 8;
- D3DCOLOR color[colors] = {
- cs.cTextFore,
- cs.cTextHighlight,
- cs.cCalloutLine,
- cs.cCalloutHighlight,
- cs.cBorder,
- cs.cControlFill,
- cs.cHighlightFill,
- cs.cAreaFill
- };
-
- for (int i = 0; i < colors; i++)
- if (color[i])
- return FALSE;
-
- return TRUE;
- }
-
- // D3DCOLOR2COLORREF swaps the blue and red components since GDI and D3D store RGB in the opposite order.
- // It also removes the alpha component as the GDI doesn't use that, and including it causes incorrect color.
- COLORREF D3DCOLOR2COLORREF(D3DCOLOR c)
- {
- LPBYTE pC = (LPBYTE)&c;
-
- return (COLORREF)((DWORD(*pC) << 16) + (DWORD(*(pC+1)) << 8) + DWORD(*(pC+2)));
- }
-